#pragma once

#include <list>
#include <memory>
#include <functional>

#include <math.h>

#include "../Math/Vector2.h"
#include "../Math/Matrix.h"
#include "../Utils/RandomUtil.h"
#include "../Neuron/SOMNeuron.h"

using namespace std;

class SOM 
{
public:
	friend class CSOMLearn;

public:
	SOM() = delete;

	SOM(int nInputDimension, int hNeuronCount, int vNeuronCount, double weightMIN, double weightMAX, shared_ptr<ITransferFunctionBase> & fTransFunc);

public:
	virtual bool Save(const char * szFileName = nullptr);

	virtual bool Load(const char * szFileName = nullptr);

	virtual void Execute(Vector2 InputData, int & hitX, int & hitY);

public:
	int GetInputDimension() const;

	void GetNeuronMatrixSize(int & hCount, int & vCount);

	void ForEachNeuron(function<void(const SOMNeuron & neuron)> callback);

protected:
	const SOMNeuron * FindArgminNeuron(Vector2 & X);

protected:
	int m_InputDimension;

	int m_HorizontalNeuronCount;
	int m_VerticalNeuronCount;

	list< shared_ptr<SOMNeuron> > m_Neurons;
};